home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / elm / elm2.4 / src / mailmsg1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-08  |  14.4 KB  |  486 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: mailmsg1.c,v 5.6 1993/05/08 20:25:33 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 5.6 $   $State: Exp $
  6.  *
  7.  *            Copyright (c) 1988-1992 USENET Community Trust
  8.  *            Copyright (c) 1986,1987 Dave Taylor
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein, Elm Coordinator
  13.  *    elm@DSI.COM            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log: mailmsg1.c,v $
  17.  * Revision 5.6  1993/05/08  20:25:33  syd
  18.  * Add sleepmsg to control transient message delays
  19.  * From: Syd
  20.  *
  21.  * Revision 5.5  1993/04/12  02:34:36  syd
  22.  * I have now added a parameter which controls whether want_to clears the
  23.  * line and centers the question or behaves like it did before. I also
  24.  * added a 0 at the end of the parameter list to all the other calls to
  25.  * want_to where a centered question on a clean line is not desirable.
  26.  * From: Jukka Ukkonen <ukkonen@csc.fi>
  27.  *
  28.  * Revision 5.4  1993/02/03  17:12:53  syd
  29.  * move more declarations to defs.h, including sleep
  30.  * From: Syd
  31.  *
  32.  * Revision 5.3  1992/12/24  21:42:01  syd
  33.  * Fix messages and nls messages to match.  Plus use want_to
  34.  * where appropriate.
  35.  * From: Syd, via prompting from Jan Djarv <Jan.Djarv@sa.erisoft.se>
  36.  *
  37.  * Revision 5.2  1992/12/20  05:15:58  syd
  38.  * Add a c)hange alias, -u and -t options to listalias to list only user
  39.  * and only system aliases respectively.
  40.  * From: "Robert L. Howard" <robert.howard@matd.gatech.edu>
  41.  *
  42.  * Revision 5.1  1992/10/03  22:58:40  syd
  43.  * Initial checkin as of 2.4 Release at PL0
  44.  *
  45.  *
  46.  ******************************************************************************/
  47.  
  48. /** Interface to allow mail to be sent to users.  Part of ELM  **/
  49.  
  50.  
  51. #include "headers.h"
  52. #include "s_elm.h"
  53.  
  54. /** strings defined for the hdrconfg routines **/
  55.  
  56. char subject[SLEN], in_reply_to[SLEN], expires[SLEN],
  57.      action[SLEN], priority[SLEN], reply_to[SLEN], to[VERY_LONG_STRING], 
  58.      cc[VERY_LONG_STRING], expanded_to[VERY_LONG_STRING], 
  59.      expanded_reply_to[LONG_STRING],
  60.      expanded_cc[VERY_LONG_STRING], user_defined_header[SLEN],
  61.      bcc[VERY_LONG_STRING], expanded_bcc[VERY_LONG_STRING],
  62.      precedence[SLEN], expires_days[SLEN];
  63.  
  64. char *format_long(), *strip_commas(), *tail_of_string();
  65.  
  66. static int to_line, to_col;
  67.  
  68. void
  69. output_abbreviated_to(address)
  70. char *address;
  71. {
  72.     /** Output just the fields in parens, separated by commas if need
  73.         be, and up to COLUMNS-50 characters...This is only used if the
  74.         user is at level BEGINNER.
  75.     **/
  76.  
  77.     char newaddress[LONG_STRING];
  78.     register int iindex, newindex = 0, in_paren = 0, add_len;
  79.  
  80.     iindex = 0;
  81.  
  82.     add_len = strlen(address);
  83.     while (newindex < 55 && iindex < add_len) {
  84.       if (address[iindex] == '(') in_paren++;
  85.       else if (address[iindex] == ')') { 
  86.         in_paren--;
  87.         if (iindex < add_len-4) {
  88.           newaddress[newindex++] = ',';
  89.           newaddress[newindex++] = ' ';
  90.         }
  91.       }
  92.       
  93.       /* copy if in_paren but not at the opening outer parens */
  94.       if (in_paren && !(address[iindex] == '(' && in_paren == 1))
  95.           newaddress[newindex++] = address[iindex];
  96.          
  97.       iindex++;
  98.     }
  99.  
  100.     newaddress[newindex] = '\0';
  101.  
  102.     if (mail_only)
  103.       if (strlen(newaddress) > 80) 
  104.         PutLine1(to_line, to_col, "To: (%s)", 
  105.            tail_of_string(newaddress, 60));
  106.       else
  107.         PutLine1(to_line, to_col, "To: %s", newaddress);
  108.     else if (strlen(newaddress) > 50) 
  109.        PutLine1(to_line, to_col, "To: (%s)", 
  110.            tail_of_string(newaddress, 40));
  111.      else {
  112.        if (strlen(newaddress) > 30)
  113.          PutLine1(to_line, to_col, "To: %s", newaddress);
  114.        else
  115.          PutLine1(to_line, to_col, "          To: %s", newaddress);
  116.        CleartoEOLN();
  117.      }
  118.  
  119.     return;
  120. }
  121.  
  122. void
  123. display_to(address)
  124. char *address;
  125. {
  126.     /** Simple routine to display the "To:" line according to the
  127.         current configuration (etc)                   
  128.      **/
  129.     register int open_paren;
  130.  
  131.     to_line = mail_only ? 3 : LINES - 3;
  132.     to_col = mail_only ? 0 : COLUMNS - 50;
  133.     if (names_only)
  134.       if ((open_paren = chloc(address, '(')) > 0) {
  135.         if (open_paren < chloc(address, ')')) {
  136.           output_abbreviated_to(address);
  137.           return;
  138.         } 
  139.       }
  140.     if(mail_only)
  141.       if(strlen(address) > 80)
  142.         PutLine1(to_line, to_col, "To: (%s)", 
  143.             tail_of_string(address, 75));
  144.       else
  145.         PutLine1(to_line, to_col, "To: %s", address);
  146.     else if (strlen(address) > 45) 
  147.       PutLine1(to_line, to_col, "To: (%s)", 
  148.           tail_of_string(address, 40));
  149.     else {
  150.       if (strlen(address) > 30) 
  151.         PutLine1(to_line, to_col, "To: %s", address);
  152.       else
  153.         PutLine1(to_line, to_col, "          To: %s", address);
  154.       CleartoEOLN();
  155.     }
  156. }
  157.  
  158. int
  159. get_to(to_field, address)
  160. char *to_field, *address;
  161. {
  162.     /** prompt for the "To:" field, expanding into address if possible.
  163.         This routine returns ZERO if errored, or non-zero if okay **/
  164.  
  165.     if (strlen(to_field) == 0) {
  166.       if (user_level < 2) {
  167.         PutLine0(LINES-2, 0, catgets(elm_msg_cat, ElmSet, ElmSendTheMessageTo,
  168.         "Send the message to: "));
  169.         (void) optionally_enter(to_field, LINES-2, 21, FALSE, FALSE); 
  170.       }
  171.       else {
  172.         PutLine0(LINES-2, 0, catgets(elm_msg_cat, ElmSet, ElmTo, "To: "));
  173.         (void) optionally_enter(to_field, LINES-2, 4, FALSE, FALSE); 
  174.       }
  175.       if (strlen(to_field) == 0) {
  176.         ClearLine(LINES-2);    
  177.         return(0);
  178.       }
  179.       (void) build_address(strip_commas(to_field), address); 
  180.     }
  181.     else if (mail_only) 
  182.       (void) build_address(strip_commas(to_field), address); 
  183.     else 
  184.       strcpy(address, to_field);
  185.     
  186.     if (strlen(address) == 0) {    /* bad address!  Removed!! */
  187.       ClearLine(LINES-2);
  188.       return(0);
  189.     }
  190.  
  191.     return(1);        /* everything is okay... */
  192. }
  193.  
  194. int
  195. send_msg(given_to, given_cc, given_subject, edit_message, form_letter, replying)
  196. char *given_to, *given_cc, *given_subject;
  197. int   edit_message, form_letter, replying;
  198. {
  199.     /** Prompt for fields and then call mail() to send the specified
  200.         message.  If 'edit_message' is true then don't allow the
  201.             message to be edited. 'form_letter' can be "YES" "NO" or "MAYBE".
  202.         if YES, then add the header.  If MAYBE, then add the M)ake form
  203.         option to the last question (see mailsg2.c) etc. etc. 
  204.         if (replying) then add an In-Reply-To: header...
  205.         Return TRUE if the main part of the screen has been changed
  206.         (useful for knowing whether a redraw is needed.
  207.     **/
  208.  
  209.     int  copy_msg = FALSE, is_a_response = FALSE;
  210.  
  211.     /* First: zero all current global message strings */
  212.  
  213.     cc[0] = bcc[0] = reply_to[0] = expires[0] = '\0';
  214.     action[0] = priority[0] = user_defined_header[0] = in_reply_to[0] ='\0';
  215.     expanded_to[0] = expanded_cc[0] = expanded_bcc[0] = '\0';
  216.     expanded_reply_to[0] = precedence[0] = expires_days[0] = '\0';
  217.  
  218.     strcpy(subject, given_subject);        /* copy given subject */
  219.     strcpy(to, given_to);            /* copy given to:     */
  220.     strcpy(cc, given_cc);            /*  and so on..       */
  221.  
  222.     /******* And now the real stuff! *******/
  223.  
  224.     copy_msg=copy_the_msg(&is_a_response); /* copy msg into edit buffer? */
  225.  
  226.     if (get_to(to, expanded_to) == 0)   /* get the To: address and expand */
  227.       return(0);
  228.     if ( cc[0] != '\0' )            /* expand out CC addresses */
  229.       build_address(strip_commas(cc), expanded_cc);
  230.  
  231.     /** if we're batchmailing, let's send it and GET OUTTA HERE! **/
  232.  
  233.     if (batch_only) {
  234.       return(mail(FALSE, FALSE, form_letter));
  235.     }
  236.  
  237.     display_to(expanded_to);    /* display the To: field on screen... */
  238.  
  239.     if (get_subject(subject) == 0)        /* get the Subject: field */
  240.       return(0);
  241.  
  242.     if (prompt_for_cc) {
  243.       if (get_copies(cc, expanded_to, expanded_cc, copy_msg) == 0)
  244.         return(0);
  245.     }
  246.  
  247.     MoveCursor(LINES,0);    /* so you know you've hit <return> ! */
  248.  
  249.     /** generate the In-Reply-To: header... **/
  250.  
  251.     if (is_a_response && replying)
  252.       generate_reply_to(current-1);
  253.  
  254.     /* and mail that puppy outta here! */
  255.     
  256.     dprint(3, (debugfile, "\nsend_msg() ready to mail...\n"));
  257.     dprint(3, (debugfile, "to=\"%s\" expanded_to=\"%s\"\n",to,expanded_to));
  258.     dprint(4, (debugfile, "subject=\"%s\"\n",subject));
  259.     dprint(5, (debugfile, "cc=\"%s\" expanded_cc=\"%s\"\n",cc,expanded_cc));
  260.     dprint(5, (debugfile, "bcc=\"%s\" expanded_bcc=\"%s\"\n",bcc,expanded_bcc));
  261.     return(mail(copy_msg, edit_message, form_letter));
  262. }
  263.  
  264. int
  265. get_subject(subject_field)
  266. char *subject_field;
  267. {
  268.     char    ch, msgbuf[SLEN];
  269.  
  270.     /** get the subject and return non-zero if all okay... **/
  271.     int len = 9, prompt_line;
  272.  
  273.     prompt_line = mail_only ? 4 : LINES-2;
  274.  
  275.     if (user_level == 0) {
  276.       PutLine0(prompt_line,0, catgets(elm_msg_cat, ElmSet, ElmSubjectOfMessage,
  277.         "Subject of message: "));
  278.       len = 20;
  279.     }
  280.     else
  281.       PutLine0(prompt_line,0, catgets(elm_msg_cat, ElmSet, ElmSubject, "Subject: "));
  282.  
  283.     CleartoEOLN();
  284.  
  285.     if(optionally_enter(subject_field, prompt_line, len, TRUE, FALSE)==-1){
  286.       /** User hit the BREAK key! **/
  287.       MoveCursor(prompt_line,0);     
  288.       CleartoEOLN();
  289.       error(catgets(elm_msg_cat, ElmSet, ElmMailNotSent, "Mail not sent."));
  290.       return(0);
  291.     }
  292.  
  293.     if (strlen(subject_field) == 0) {    /* zero length subject?? */
  294.       MCsprintf(msgbuf, catgets(elm_msg_cat, ElmSet, ElmNoSubjectContinue,
  295.         "No subject - Continue with message? (%c/%c) "),
  296.         *def_ans_yes, *def_ans_no);
  297.  
  298.       ch = want_to(msgbuf, *def_ans_no, prompt_line, 0);
  299.       if (ch != *def_ans_yes) {    /* user says no! */
  300.         if (sleepmsg > 0)
  301.         sleep((sleepmsg + 1) / 2);
  302.         ClearLine(prompt_line);
  303.         error(catgets(elm_msg_cat, ElmSet, ElmMailNotSend, "Mail not sent."));
  304.         return(0);
  305.       }
  306.       else {
  307.         PutLine0(prompt_line,0,"Subject: <none>");
  308.         CleartoEOLN();
  309.       }
  310.     }
  311.  
  312.     return(1);        /** everything is cruising along okay **/
  313. }
  314.  
  315. int
  316. get_copies(cc_field, address, addressII, copy_message)
  317. char *cc_field, *address, *addressII;
  318. int   copy_message;
  319. {
  320.     /** Get the list of people that should be cc'd, returning ZERO if
  321.         any problems arise.  Address and AddressII are for expanding
  322.         the aliases out after entry! 
  323.         If 'bounceback' is nonzero, add a cc to ourselves via the remote
  324.         site, but only if hops to machine are > bounceback threshold.
  325.         If copy-message, that means that we're going to have to invoke
  326.         a screen editor, so we'll need to delay after displaying the
  327.         possibly rewritten Cc: line...
  328.     **/
  329.     int prompt_line;
  330.  
  331.     prompt_line = mail_only ? 5 : LINES - 1;
  332.     PutLine0(prompt_line,0, catgets(elm_msg_cat, ElmSet, ElmCopiesTo, "Copies to: "));
  333.  
  334.     fflush(stdout);
  335.  
  336.     if (optionally_enter(cc_field, prompt_line, 11, FALSE, FALSE) == -1) {
  337.       ClearLine(prompt_line-1);
  338.       ClearLine(prompt_line);
  339.       
  340.       error(catgets(elm_msg_cat, ElmSet, ElmMailNotSend, "Mail not sent."));
  341.       return(0);
  342.     }
  343.     
  344.     /** The following test is that if the build_address routine had
  345.         reason to rewrite the entry given, then, if we're mailing only
  346.         print the new Cc line below the old one.  If we're not, then
  347.         assume we're in screen mode and replace the incorrect entry on
  348.         the line above where we are (e.g. where we originally prompted
  349.         for the Cc: field).
  350.     **/
  351.  
  352.     if (build_address(strip_commas(cc_field), addressII)) {
  353.       PutLine1(prompt_line, 11, "%s", addressII);
  354.       if ((strcmp(editor, "builtin") != 0 && strcmp(editor, "none") != 0)
  355.           || copy_message)
  356.         if (sleepmsg > 0)
  357.         sleep(sleepmsg);
  358.     }
  359.  
  360.     if (strlen(address) + strlen(addressII) > VERY_LONG_STRING) {
  361.       dprint(2, (debugfile, 
  362.         "String length of \"To:\" + \"Cc\" too long! (get_copies)\n"));
  363.       error(catgets(elm_msg_cat, ElmSet, ElmTooManyPeople, "Too many people. Copies ignored."));
  364.       if (sleepmsg > 0)
  365.         sleep(sleepmsg);
  366.       cc_field[0] = '\0';
  367.     }
  368.  
  369.     return(1);        /* everything looks okay! */
  370. }
  371.     
  372. int
  373. copy_the_msg(is_a_response)
  374. int *is_a_response;
  375. {
  376.     /** Returns True iff the user wants to copy the message being
  377.         replied to into the edit buffer before invoking the editor! 
  378.         Sets "is_a_response" to true if message is a response...
  379.     **/
  380.  
  381.     char msg[SLEN];
  382.     int answer = FALSE;
  383.  
  384.     if (forwarding)
  385.       answer = TRUE;
  386.     else if (strlen(to) > 0 && !mail_only) {  /* predefined 'to' line! */
  387.       if (auto_copy) 
  388.         answer = TRUE;
  389.       else {
  390.         MCsprintf(msg, catgets(elm_msg_cat, ElmSet, ElmCopyMessageYN,
  391.         "Copy message? (%c/%c) "), *def_ans_yes, *def_ans_no);
  392.         answer = (want_to(msg, *def_ans_no, LINES-3, 0) == *def_ans_yes);
  393.       }
  394.       *is_a_response = TRUE;
  395.     }
  396.  
  397.     return(answer);
  398. }
  399.  
  400. int
  401. a_sendmsg(edit_message, form_letter)
  402. int   edit_message, form_letter;
  403. {
  404.     /** Prompt for fields and then call mail() to send the specified
  405.         message.  If 'edit_message' is true then don't allow the
  406.             message to be edited. 'form_letter' can be "YES" "NO" or "MAYBE".
  407.         if YES, then add the header.  If MAYBE, then add the M)ake form
  408.         option to the last question (see mailsg2.c) etc. etc. 
  409.  
  410.         Return TRUE if the main part of the screen has been changed
  411.         (useful for knowing whether a redraw is needed.
  412.     **/
  413.  
  414.     register int tagged = 0, i;
  415.     int ret;
  416.  
  417.     /* First: zero all current global message strings */
  418.  
  419.     cc[0] = bcc[0] = reply_to[0] = expires[0] = '\0';
  420.     action[0] = priority[0] = user_defined_header[0] = in_reply_to[0] ='\0';
  421.     expanded_to[0] = expanded_cc[0] = expanded_bcc[0] = '\0';
  422.     cc[0] = subject[0] = to[0] = '\0';
  423.     expanded_reply_to[0] = precedence[0] = expires_days[0] = '\0';
  424.  
  425.     for (i=0; i < message_count; i++) {
  426.       if (ison(aliases[i]->status, TAGGED)) {
  427.         strcat(to, aliases[i]->alias);
  428.         strcat(to, " ");
  429.         tagged++;
  430.       }
  431.     }
  432.  
  433.     if (tagged == 0) {
  434.       strcpy(to, aliases[current-1]->alias);
  435.     }
  436.  
  437.     dprint(4, (debugfile, "%d aliases tagged for mailing (a_sndmsg)\n",
  438.             tagged));
  439.  
  440.     /******* And now the real stuff! *******/
  441.  
  442.     if (build_address(to, expanded_to) == 0)   /* build the To: address and expand */
  443.       return(0);
  444.     if ( cc[0] != '\0' )            /* expand out CC addresses */
  445.       build_address(strip_commas(cc), expanded_cc);
  446.  
  447.     display_to(expanded_to);    /* display the To: field on screen... */
  448.  
  449.     if (get_subject(subject) == 0)        /* get the Subject: field */
  450.       return(0);
  451.  
  452.     if (prompt_for_cc) {
  453.       if (get_copies(cc, expanded_to, expanded_cc, FALSE) == 0)
  454.         return(0);
  455.     }
  456.  
  457.     MoveCursor(LINES,0);    /* so you know you've hit <return> ! */
  458.  
  459.     /* and mail that puppy outta here! */
  460.     
  461.     dprint(3, (debugfile, "\na_sendmsg() ready to mail...\n"));
  462.     dprint(3, (debugfile, "to=\"%s\" expanded_to=\"%s\"\n",to,expanded_to));
  463.     dprint(4, (debugfile, "subject=\"%s\"\n",subject));
  464.     dprint(5, (debugfile, "cc=\"%s\" expanded_cc=\"%s\"\n",cc,expanded_cc));
  465.     dprint(5, (debugfile, "bcc=\"%s\" expanded_bcc=\"%s\"\n",bcc,expanded_bcc));
  466.  
  467.     main_state();
  468.     ret = mail(FALSE, edit_message, form_letter);
  469.     main_state();
  470.  
  471. /*
  472.  *    Since we got this far, it must be okay to clear the tags.
  473.  */
  474.     i = 0;
  475.     while (tagged) {
  476.         if (ison(aliases[i]->status, TAGGED)) {
  477.             clearit(aliases[i]->status, TAGGED);
  478.             show_msg_tag(i);
  479.             tagged--;
  480.         }
  481.         i++;
  482.     }
  483.  
  484.     return(ret);
  485. }
  486.